IOS KVC 筆記

KVC可以存取純量(scalar,我的感覺就是基礎型別,如:(int, bool)以及結構(struct)。

如同KVC存取物件一樣實現setter(-set<Key>:) & getter(-<key>) 方法。

但是透過KVC去存取的話,必需進行打包和解包的動作。

純量 VS NSNumber,結構 VS NSValue。

例如:

  • 透過KVC存值給int型別必須透過NSNumber去存取

    [self setValue:@100 forKey:@"x"]

  • 透過KVC去取int型別的值也是回傳NSNumber

    NSNumber *number = [self valueForKey:@"x"]

在我們想要透過KVC存取純量及結構的同時,我們也必須實現setNilValueForKey:方法,因為我們有可能透過KVC setter存入一個nil進去。
純量存取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@interface MyClass
@property (nonatomic) float f;
@end

@implementation MyClass
-(void)test{
_f = 100; // f = 100
[self valueForKey:@"f"]; // 100
[self setValue:@200 forKey:@"f"]; // f = 200

// will run setNilValueForKey
[self setValue:nil forKey:@"f"]; // f = 5

// compile fail
//self.f = nil;
}

-(void)setNilValueForKey:(NSString *)key{
if([key isEqualToString:@"f"]){
_f = 5;
//[self setValue:@5 forKey:@"f"];
}else{
[super setNilValueForKey:theKey];
}
}

結構存取
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
typedef struct {
float x, y, z;
} ThreeFloats;

@interface MyClass{

}
@property (nonatomic) ThreeFloats threeFloats;
@end

@implementation MyClass

@synthesize threeFloats = _threeFloats;

-(void)test{
_threeFloats.x=11;
_threeFloats.y=22;
_threeFloats.z=33;

NSValue *gValue = [self valueForKey:@"threeFloats"];
ThreeFloats f3;
[gValue getValue:&f3];

f3.x = 100;
NSValue *sValue = [NSValue value:&f3 withObjCType:@encode(ThreeFloats)];
[self setValue:sValue forKey:@"threeFloats"];
}

- (void)setThreeFloats:(ThreeFloats)threeFloats{
_threeFloats = threeFloats;
}

- (ThreeFloats)threeFloats{
return _threeFloats;
}
@end

詭異點(小細節??)

這篇有提到說請確保與KVC相容 Ensuring KVC Compliance

  • Implement a method named -<key>, -is<Key>
  • or have an instance variable <key> or _<key>
  • If the property is mutable, then it should also implement -set<Key>:

getter依序註解getFf,ff,isFf

setter依序註解setFf:

KVC getter & setter test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@interface MyClass
@property (nonatomic,getter=issFf,setter=ssetFf:) float ff;
@end

@implementation MyClass

@synthesize ff = _ff;

-(void)test{
NSNumber *fff = [self valueForKeyPath:@"ff"];
[self setValue:@2000 forKey:@"ff"]; }

-(void)setFf:(float)value{
_ff = value;
}

-(void)ssetFf:(float)value{
_ff = value;
}

-(float)getFf{
return _ff+1;
}

-(float)ff{
return _ff+2;
}

-(float)isFf{
return _ff+3;
}

-(float)issFf{
return _ff+4;
}
@end

相關文章: